home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)doSymbols.c 1.7 1/20/89
- */
- #include "assert.h"
- #include "error.h"
- #include "scan.h"
- #include "nodes.h"
- #include "symbols.h"
- #include "MyParser.h"
- #include "sequence.h"
- #include "semantics.h"
- #include "map.h"
- #include "system.h"
- #include "flags.h"
- #include "trace.h"
- #include "opNames.h"
- extern void defineGlobal(), resolveGlobal();
- extern NodePtr buildSymbol();
- extern Map objectTable;
- Boolean opNamesResolved = FALSE;
-
- typedef struct sIDesc {
- NodePtr object;
- unsigned int nestingDepth :16;
- Boolean inMonitor :1;
- Boolean inInit :1;
- Boolean inBlock :1;
- Boolean movesThings :1;
- Boolean movesSelf :1;
- unsigned int unused :11;
- struct sIDesc *next;
- } IDesc, *IDescPtr;
-
- extern int nestingDepth;
- static IDescPtr stack = NULL;
-
- static void push(p)
- NodePtr p;
- {
- register IDescPtr t;
- t = (IDescPtr) calloc(1, sizeof(IDesc));
- t->object = p;
- t->nestingDepth = nestingDepth;
- t->next = stack;
- stack = t;
- }
-
- static void pop()
- {
- IDescPtr this;
-
- /* Pop it from the stack. */
- this = stack;
- this->object->b.oblit.f.doesNotMoveArguments = !this->movesThings;
- this->object->b.oblit.f.doesNotMoveSelf = !this->movesSelf;
- stack = this->next;
- free((char *)this);
- }
-
- static DefineASymbol(p, fKind, isAttached, isMove)
- register NodePtr p;
- ST_Kinds fKind;
- Boolean isAttached, isMove;
- {
- assert(p->tag == P_SYMDEF);
- p->b.symdef.symbol = ST_Define(p->b.symdef.ident, fKind, 1);
- if (p->b.symdef.symbol == 0) {
- fprintf(stdout, "\"%s\", line %d: %s redefined.\n",
- currentFileName, p->lineNumber,
- Ident_Name(p->b.symdef.ident));
- numberOfSemanticErrors++;
- } else {
- p->b.symdef.symbol->isAttached = isAttached;
- p->b.symdef.symbol->isMove = isMove;
- }
- }
-
- static void DefineAName(p)
- NodePtr p;
- {
- assert(p->tag == P_OPNAME);
- }
-
- /*
- * This is called during define symbols, so the symbol field of symbols is
- * not defined yet. We now compare on the ident field, since these are in
- * the same scope.
- */
-
- static NodePtr findWhereValue(sym, type, where)
- NodePtr sym, type, *where;
- {
- register NodePtr p, q, w = *where;
- NodePtr resultWW, resultValue;
- Boolean foundIt = FALSE;
- if (type->tag != P_BUILTINLIT ||
- type->b.builtinlit.whichType != KABSTRACTTYPE) return(NN);
- Sequence_For(p, w)
- assert(p->tag == P_WHEREWIDGIT);
- if (foundIt) {
- w->b.children[z__z - 1] = p;
- } else {
- q = p->b.wherewidgit.sym;
- if (q->b.symref.ident == sym->b.symref.ident) {
- foundIt = TRUE;
- resultWW = p;
- if (q->tag == P_SYMDEF) {
- ErrorMessage(q, "Type parameters must be constrained using *>");
- resultValue = NN;
- } else {
- assert(q->tag == P_SYMREF);
- resultValue = resultWW->b.wherewidgit.type;
- }
- }
- }
- Sequence_Next
- if (foundIt) {
- assert(resultWW->tag == P_WHEREWIDGIT);
- w->nChildren --;
- resultWW->b.wherewidgit.type = NULL;
- FreeNode(resultWW);
- return(resultValue);
- } else {
- resultValue = Construct(P_BUILTINLIT, 0);
- resultValue->b.builtinlit.whichType = KANY;
- return(resultValue);
- }
- }
-
- static void checkFunction(p)
- register NodePtr p;
- {
- assert(p->tag == P_OPSIG);
- if (p->b.opsig.isFunction) {
- if (Sequence_Length(p->b.opsig.results) != 1) {
- ErrorMessage(p, "Functions must return one result (not %d)",
- Sequence_Length(p->b.opsig.results));
- }
- }
- }
-
- static void defineSymbols(p)
- NodePtr p;
- {
- register NodePtr q, r;
- NodePtr whereValue;
- int doExit = 0;
-
- if (p == NN) {
- return;
- } else if ((int)p < 0x200) {
- /* it is probably an input token */
- return;
- } else {
- switch (p->tag) {
- case P_UNAVAILABLEHANDLER:
- doExit = 1;
- ST_EnterNewScope(p, C_UnavailableHandler);
- break;
- case P_VARDECL:
- DefineASymbol(p->b.vardecl.sym, ST_Var, p->b.vardecl.isAttached, FALSE);
- break;
- case P_CONSTDECL:
- DefineASymbol(p->b.constdecl.sym, ST_Const, p->b.constdecl.isAttached, FALSE);
- break;
- case P_PARAM:
- /* unavailables show up here */
- DefineASymbol(p->b.param.sym, ST_Param, p->b.param.isAttached, p->b.param.move);
- break;
- case P_WHEREWIDGIT:
- if ((int)(p->b.wherewidgit.op) == OIDENTITY) {
- assert(p->b.wherewidgit.sym->tag == P_SYMDEF);
- DefineASymbol(p->b.wherewidgit.sym, ST_Const, FALSE, FALSE);
- } else {
- /*
- * We have not a definition but a constraint one here.
- * Just make sure that this is a symbol reference.
- */
- assert((int)p->b.wherewidgit.op == OCONFORMSTO);
- assert(p->b.wherewidgit.sym->tag == P_SYMREF);
- }
- break;
- case P_ENUMLIT:
- NotImplemented(p, "enumeration literals");
- break;
- case P_UNIONLIT:
- NotImplemented(p, "union literals");
- break;
- case P_RECORDLIT:
- NotImplemented(p, "record literals");
- break;
- case P_IMPORT:
- q = p->b.import.syms;
- Sequence_For(r, q)
- DefineASymbol(r, ST_Const, FALSE, FALSE);
- Sequence_Next
- break;
- case P_ATLIT:
- ST_EnterNewScope(p, C_ATLit);
- if (p->b.atlit.name != NN)
- DefineASymbol(p->b.atlit.name, ST_Const, FALSE, FALSE);
- q = p->b.atlit.ops;
- /* q is a sequence of operation signatures. */
- Sequence_For(r, q)
- ST_EnterNewScope(r, C_OpSig);
- defineSymbols(r);
- checkFunction(r);
- ST_ExitScope();
- Sequence_Next
- ST_ExitScope();
- return;
- /*break;*/
- case P_OPSIG:
- DefineAName(p->b.opsig.name);
- checkFunction(p);
- q = p->b.opsig.params;
- /* q is the parameter list. */
- Sequence_For(r, q)
- assert(r->tag == P_PARAM);
- assert(r->b.param.sym != NN);
- whereValue =
- findWhereValue(r->b.param.sym, r->b.param.type,
- &p->b.opsig.where);
- if (whereValue != NN) {
- /*
- * This operation has a parameter that is a type. This means
- * that the operation can only be called at compile time.
- */
- p->b.opsig.mustBeCompilerExecuted = TRUE;
- defineSymbols(whereValue);
- }
- r->b.param.constraint = whereValue;
- DefineASymbol(r->b.param.sym, ST_Param, r->b.param.isAttached, r->b.param.move);
- defineSymbols(r->b.param.type);
- Sequence_Next
- q = p->b.opsig.results;
- /* q is the result list. */
- Sequence_For(r, q)
- assert(r->tag == P_PARAM);
- assert(r->b.param.sym != NN);
- DefineASymbol(r->b.param.sym, ST_Result, r->b.param.isAttached, r->b.param.move);
- defineSymbols(r->b.param.type);
- Sequence_Next
- defineSymbols(p->b.opsig.where);
- return;
- /*break;*/
- case P_SYMDEF:
- break;
- /* enter block */
- case P_OBLIT:
- ST_EnterNewScope(p, C_ObLit);
- assert (p->b.oblit.name != NN);
- DefineASymbol(p->b.oblit.name, ST_Const, FALSE, FALSE);
- Sequence_For(q, p)
- defineSymbols(q);
- Sequence_Next
- ST_ExitScope();
- return;
- case P_OPDEF:
- doExit = 1;
- ST_EnterNewScope(p, C_OpDef);
- break;
- case P_COMP:
- doExit = 1;
- ST_EnterNewScope(p, C_Comp);
- break;
- case P_MONITOR:
- doExit = 1;
- ST_EnterNewScope(p, C_Monitor);
- break;
- case P_IFCLAUSE:
- defineSymbols(p->b.ifclause.exp);
- ST_EnterNewScope(p, C_Block);
- defineSymbols(p->b.ifclause.stats);
- ST_ExitScope();
- return;
- case P_BLOCK:
- case P_ELSECLAUSE:
- case P_LOOPSTAT:
- case P_FAILUREHANDLER:
- doExit = 1;
- ST_EnterNewScope(p, C_Block);
- break;
- }
- Sequence_For(r, p)
- defineSymbols(r);
- Sequence_Next
- if (doExit) ST_ExitScope();
- }
- }
-
- extern int compareSigs();
-
- static int compareDefs(a, b)
- NodePtr *a, *b;
- {
- assert((*a)->tag == P_OPDEF);
- assert((*a)->b.opdef.sig->tag == P_OPSIG);
- assert((*a)->b.opdef.sig->b.opsig.name->tag == P_OPNAME);
- assert((*b)->tag == P_OPDEF);
- assert((*b)->b.opdef.sig->tag == P_OPSIG);
- assert((*b)->b.opdef.sig->b.opsig.name->tag == P_OPNAME);
- return((*a)->b.opdef.sig->b.opsig.name->b.opname.id -
- (*b)->b.opdef.sig->b.opsig.name->b.opname.id);
- }
-
- #define MAXOPS 500
- static void sortConcreteOps(ct)
- register NodePtr ct;
- {
- NodePtr opArray[MAXOPS], ops, p;
- register int nextFree = 0, i;
- int stage;
- OID prevOp, thisOp;
-
- assert(ct->tag == P_OBLIT);
- for (stage = 0; stage < 2; stage++) {
- if (stage == 0) {
- ops = ct->b.oblit.monitor;
- if (ops != NULL) {
- assert(ops->tag == P_MONITOR);
- ops = ops->b.monitor.ops;
- }
- } else if (stage == 1) {
- ops = ct->b.oblit.ops;
- }
- Sequence_For(p, ops)
- assert(p->tag == P_OPDEF);
- assert(nextFree < MAXOPS);
- opArray[nextFree++] = p;
- Sequence_Next
- }
- TRACE1(atctsort, 2, "QSorting ct named %s", ATName(ct));
- qsort((char *)opArray, nextFree, sizeof(NodePtr), compareDefs);
- prevOp = 0;
- for (i = 0; i < nextFree; i++) {
- TRACE2(atctsort, 4, "Operation %s has number %d",
- SigName(opArray[i]->b.opdef.sig), i);
- opArray[i]->b.opdef.opNumber = i;
- thisOp = opArray[i]->b.opdef.sig->b.opsig.name->b.opname.id;
- if (prevOp == thisOp) {
- ErrorMessage(ct, "Object \"%s\" multiply defines operation \"%s\"",
- ST_SymbolName(ct->b.oblit.name->b.symdef.symbol),
- ON_Name(prevOp));
- }
- prevOp = thisOp;
- }
- }
-
- void sortATOps(p)
- NodePtr p;
- {
- OID prevOp, thisOp;
- register int i;
- if (Sequence_Length(p->b.atlit.ops) > 1) {
- TRACE1(atctsort, 2, "QSorting at named %s", ATName(p));
- qsort((char *)&(p->b.atlit.ops->b.children[0]),
- Sequence_Length(p->b.atlit.ops),
- sizeof(NodePtr),
- compareSigs);
- prevOp = 0;
- for (i = 0; i < Sequence_Length(p->b.atlit.ops); i++) {
- TRACE2(atctsort, 4, "Operation %s has number %d",
- SigName(p->b.atlit.ops->b.children[i]), i);
- thisOp = p->b.atlit.ops->b.children[i]->b.opsig.name->b.opname.id;
- if (prevOp == thisOp) {
- ErrorMessage(p, "Type \"%s\" multiply defines operation \"%s\"",
- ST_SymbolName(p->b.atlit.name->b.symdef.symbol),
- ON_Name(prevOp));
- }
- prevOp = thisOp;
- }
- }
- }
-
- static void propagateImports(st)
- Symbol st;
- {
- Symbol ost;
- register IDescPtr idp;
- register NodePtr q;
- for (idp = stack; idp != NULL; idp = idp->next) {
- Sequence_For(q, idp->object->b.oblit.setq)
- assert(q->tag == P_SETQ);
- if (q->b.setq.inner->b.symdef.symbol == st) {
- ost = q->b.setq.outer->b.symref.symbol;
- assert(st->isImport);
- if (idp->inBlock && !idp->inInit) {
- TRACE1(imports, 1, "Symbol %s used outside initially", ST_SymbolName(st));
- st->usedOutsideInitially = TRUE;
- } else {
- TRACE1(imports, 1, "Symbol %s is not used outside initially", ST_SymbolName(st));
- }
- break;
- }
- Sequence_Next
- st = ost;
- }
- }
-
- static void checkMovedThing(p)
- NodePtr p;
- {
- Symbol movedThing, stackSymbol;
- if (p->tag == P_SYMREF) {
- movedThing = p->b.symref.symbol;
- stackSymbol = stack->object->b.oblit.name->b.symdef.symbol;
- if (stackSymbol == movedThing) {
- stack->movesSelf = TRUE;
- } else {
- stack->movesThings = TRUE;
- }
- } else {
- stack->movesThings = TRUE;
- }
- }
-
- static void resolveSymbols(p)
- register NodePtr p;
- {
- int doExit = 0, saveInBlock;
- register Symbol st;
- register NodePtr q, r, lefts;
-
- if ((int)p < 0x200) return;
- else {
- switch (p->tag) {
- case P_INITDEF:
- stack->inInit = TRUE;
- resolveSymbols(p->b.initdef.body);
- stack->inInit = FALSE;
- return;
- /* enter block */
- case P_ATLIT:
- ST_EnterOldScope(p);
- push(p);
- p->b.atlit.name->b.symdef.symbol->isSelf = TRUE;
- p->b.atlit.name->b.symdef.symbol->value.value = p;
- resolveSymbols(p->b.atlit.name);
- q = p->b.atlit.ops;
- Sequence_For(r, q)
- ST_EnterOldScope(r);
- resolveSymbols(r);
- ST_ExitScope();
- Sequence_Next
- ST_ExitScope();
- sortATOps(p);
- pop();
- return;
- /*break;*/
- case P_SELFLIT:
- p->tag = P_SYMREF;
- assert(stack != NULL);
- q = stack->object->b.oblit.name;
- assert(q->tag == P_SYMDEF);
- p->b.symref = q->b.symdef;
- break;
- case P_OBLIT:
- ST_EnterOldScope(p);
- push(p);
- p->b.oblit.name->b.symdef.symbol->isSelf = TRUE;
- p->b.oblit.name->b.symdef.symbol->value.value = p;
- Sequence_For(q, p)
- resolveSymbols(q);
- Sequence_Next
- ST_ExitScope();
- pop();
- sortConcreteOps(p);
- return;
- case P_SIGNALSTAT:
- if (!stack->inMonitor) ErrorMessage(p, "Signal statements must be in monitors");
- break;
- case P_WAITSTAT:
- if (!stack->inMonitor) ErrorMessage(p, "Wait statements must be in monitors");
- break;
- case P_RETURNSTAT:
- case P_RETURNANDFAILSTAT:
- break;
- case P_CHECKPOINTSTAT:
- if (!stack->inMonitor) ErrorMessage(p, "Checkpoint statements must be in monitors");
- break;
- case P_BLOCK:
- saveInBlock = stack->inBlock;
- stack->inBlock = TRUE;
- ST_EnterOldScope(p);
- Sequence_For(q, p)
- resolveSymbols(q);
- Sequence_Next
- stack->inBlock = saveInBlock;
- ST_ExitScope();
- return;
- case P_OPDEF:
- p->b.opdef.isMonitored = stack->inMonitor;
- ST_EnterOldScope(p);
- doExit = TRUE;
- break;
- case P_IFCLAUSE:
- resolveSymbols(p->b.ifclause.exp);
- ST_EnterOldScope(p);
- resolveSymbols(p->b.ifclause.stats);
- ST_ExitScope();
- return;
- case P_UNAVAILABLEHANDLER:
- case P_COMP:
- case P_ELSECLAUSE:
- case P_LOOPSTAT:
- case P_FAILUREHANDLER:
- ST_EnterOldScope(p);
- doExit = TRUE;
- break;
- case P_MONITOR:
- ST_EnterOldScope(p);
- stack->inMonitor = TRUE;
- resolveSymbols(p->b.monitor.decls);
- resolveSymbols(p->b.monitor.ops);
- resolveSymbols(p->b.monitor.init);
- resolveSymbols(p->b.monitor.recovery);
- stack->inMonitor = FALSE;
- ST_ExitScope();
- return;
- case P_ASSIGNSTAT:
- lefts = p->b.assignstat.left;
- Sequence_For(r, lefts)
- if (r->tag != P_SYMREF) {
- ErrorMessage(r, "Syntactic sugarings require the ':=' operator");
- resolveSymbols(r);
- } else {
- assert (r->tag == P_SYMREF);
- resolveSymbols(r);
- st = ST_Fetch(r->b.symref.symbol);
- if (st != NULL) {
- if (st->itsKind != ST_Var && st->itsKind != ST_Result) {
- ErrorMessage(p, "Assignment to non-variable");
- } else if (st->nestingDepth < stack->nestingDepth) {
- assert(FALSE);
- ErrorMessage(p, "Assignment to imported variable");
- } else if (st->nestingDepth == stack->nestingDepth && !stack->inInit) {
- ErrorMessage(p, "Assignment to non-monitored instance variables can only be made from the initially");
- }
- }
- }
- Sequence_Next
- resolveSymbols(p->b.assignstat.right);
- return;
- case P_SYMREF:
- p->b.symref.symbol = ST_Lookup(p->b.symref.ident, 2);
- if ((st = p->b.symref.symbol) == 0) {
- ErrorMessage(p, "\"%s\" undefined", Ident_Name(p->b.symref.ident));
- } else {
- #ifdef OLDSTUFF
- if (st->isImport && stack->inBlock && !stack->inInit)
- #else
- if (st->isImport && stack->inBlock)
- #endif
- propagateImports(st);
- }
- break;
- case P_CONSTDECL:
- resolveSymbols(p->b.constdecl.type);
- resolveSymbols(p->b.constdecl.value);
- return;
- case P_OPNAME:
- p->b.opname.id = ON_Translate(Ident_Name(p->b.opname.ident));
- break;
- case P_UNFIXSTAT:
- resolveSymbols(p->b.unfixstat.exp);
- checkMovedThing(p->b.unfixstat.exp);
- return;
- case P_MOVESTAT:
- case P_FIXSTAT:
- case P_REFIXSTAT:
- resolveSymbols(p->b.movestat.exp);
- resolveSymbols(p->b.movestat.loc);
- checkMovedThing(p->b.movestat.exp);
- return;
- }
- Sequence_For(q, p)
- resolveSymbols(q);
- Sequence_Next
- if (doExit) ST_ExitScope();
- }
- }
-
- void initializeSymbols()
- {
- }
-
- void processSymbols(fNodePtr)
- NodePtr fNodePtr;
- {
- defineSymbols(fNodePtr);
- resolveSymbols(fNodePtr);
- opNamesResolved = TRUE;
- }
-